---
title: "Shared Data Types"
description: "Data types that share runtime presentation between JS and ReScript"
canonical: "/docs/manual/shared-data-types"
section: "JavaScript Interop"
order: 2
---

# Shared Data Types

ReScript's built-in values of type `string`, `float`, `array` and a few others have a rather interesting property: they compile to the exact same value in JavaScript!

This means that if you're passing e.g. a ReScript string to the JavaScript side, the JS side can directly use it as a native JS string. It also means that you can import a JS string and pretend it's a native ReScript string.

Unlike most compiled-to-js languages, in ReScript, **you don't need to write data converters back and forth for most of our values**!

**Shared, bidirectionally usable types**:

- String. ReScript strings are JavaScript strings, vice-versa. (Caveat: only our backtick string `` `hello 👋 ${personName}` `` supports unicode and interpolation).
- Float. ReScript floats are JS numbers, vice-versa.
- Array. In addition to the [Array API](/docs/manual/api/stdlib/array), we provide our own [Belt.Array](/docs/manual/api/belt/array#set) API too.
- Tuple. Compiles to a JS array. You can treat a fixed-sized, heterogenous JS array as ReScript tuple too.
- Boolean.
- Record. Record compiles to JS object. Therefore you can also treat JS objects as records. If they're too dynamic, consider modeling them on the ReScript side as a hashmap/dictionary [`Dict`](/docs/manual/api/stdlib/dict) or a ReScript object.
- Object. ReScript objects are JavaScript objects, vice-versa.
- Function. They compile to clean JS functions.
- Module. ReScript files are considered top-level modules, and are compiled to JS files 1 to 1. Nested modules are compiled to JavaScript objects.
- Polymorphic variants.
- Unit. The `unit` type, which has a single value `()`, compiles to `undefined` too. Likewise, you can treat an incoming JS `undefined` as `()` if that's the only value it'll ever be.

**Types that are slightly different than JS, but that you can still use from JS**:

- Int. **Ints are 32-bits**! Be careful, you can potentially treat them as JS numbers and vice-versa, but if the number's large, then you better treat JS numbers as floats. For example, we bind to `Date` using `float`s.
- Option. The `option` type's `None` value compiles into JS `undefined`. The `Some` value, e.g. `Some(5)`, compiles to `5`. Likewise, you can treat an incoming JS `undefined` as `None`. **JS `null` isn't handled here**. If your JS value can be `null`, use [Nullable](/docs/manual/api/stdlib/nullable) helpers.
- Exception.
- Variant. Check the compiled JavaScript output of variant to see its shape. We don't recommend exporting a ReScript variant for pure JS usage, since they're harder to read as plain JS code, but you can do it.
- List, which is just a regular variant.

**Non-shared types (aka internal types)**:

- Character.
- Int64.
- Lazy values.
- Everything else.

Many of these are stable, which means that you can still serialize/deserialize them as-is without manual conversions. But we discourage actively peeking into their structure otherwise.

These types require manual conversions if you want to export them for JS consumption. For a seamless JS/TypeScript integration experience, you might want to use [genType](https://github.com/cristianoc/gentype) instead of doing conversions by hand.
